from django.db import models
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext as _
from django.contrib.auth.models import User
from django.db.models.fields.related import ForeignKey

from tagging.fields import TagField

#############################################################################################################
# CONSTANTS
#############################################################################################################

BOOL_SIZE = 1
TINY_SIZE = 3
INT_SIZE = 15
NAME_SIZE = 63
NORMAL_SIZE = 127
DESCRIPTION_SIZE = 255

"""
    Type of tasks:
        - Task : Common task made in sprint planning
        - Not scheduled task: Task made during the sprint
        - Impediment : Imped
        - Meeting :
        - Bug :
"""       

BUG = 'B'
TASK = 'T'
MEETING = 'M'
IMPEDIMENT = 'I'
NOT_SCHEDULED_TASK = 'NST'
 
TASKS_TYPE = (
    (BUG , _('Bug')),
    (TASK , _('Task')),
    (MEETING , _('Meeting')),
    (IMPEDIMENT , _('Impediment')),
    (NOT_SCHEDULED_TASK , _('Not Scheduled Task')),
)

"""
    Type of severities of BUGS:
        HIGH = 'H'
        MINOR = 'M'
        BLOCK = 'B'
        MEDIUM = 'ME'
        CRITICAL = 'C'
        SUGGESTION = 'S'
"""       

HIGH = 'H'
MINOR = 'M'
BLOCK = 'B'
MEDIUM = 'ME'
CRITICAL = 'C'
SUGGESTION = 'S'
 
SEVERITY_TYPE = (
    (HIGH , _('Hight')),
    (MINOR , _('Minor')),
    (BLOCK , _('Block')),
    (MEDIUM , _('Medium')),
    (CRITICAL , _('Critical')),
    (SUGGESTION , _('Suggestion')),
)

"""
    Status of history, tasks and every thing that has project 
"""       

OPENED = 'OPENED'
CLOSED = 'CLOSED'
REOPENED = 'REOPENED'
 
STATUS = (
    (OPENED , _('Opened')),
    (CLOSED , _('Closed')),
    (REOPENED , _('Reopened')),
)

"""
    State of histories
"""
DONE = "D"                   # Ended by PO
INCOMPLETE = "I"             # PO does not considers it complete
DONE_TO_REVIEW = "R"         # End tests and it was send to show in review
DONE_TO_TEST = "T"           # Done development and send to test
DEVELOPMENT = "E"            # History is in development state
PROMISED = "P"               # History was promissed in planning 2

HISTORY_STATUS = (
    (DONE, _('Done')) ,
    (INCOMPLETE,_('Incomplete')),
    (DONE_TO_REVIEW, _('Done to review')),
    (DONE_TO_TEST, _('Done to test')),
    (DEVELOPMENT, _('Development')),
    (PROMISED, _('Promised'))
)

"""
    Status of time log
"""       

STARTED = 'STARTED'
PAUSED = 'PAUSED'
STOPPED = 'STOPPED'
 
TIME_STATUS = (
    (STARTED , _('Started')),
    (PAUSED, _('Paused')),
    (STOPPED , _('Stopped')),
)


"""
    Sprint status
"""

PLANNING_HISTORY = 'PLANNING_HISTORY'
PLANNING_TASK = 'PLANNING_TASK'
GOAL = 'GOAL'
NOT_GOAL = 'NOT_GOAL'

SPRINT_STATUS = (
    (PLANNING_HISTORY, _('Planning')),
    (PLANNING_TASK, _('Planning')),
    (GOAL, _('Goal')),
    (NOT_GOAL, _('Not goal')),
) 
    

#############################################################################################################
# MODELS
#############################################################################################################

class BaseModel(models.Model):
    """
        Abstract class for all models. All models must have an user that was (created by and updated by), moreover
        all models must have the date that it was created and date of last update 
    """
    
    created_by = models.CharField(max_length=NORMAL_SIZE, null=True, blank=True, editable=False)
    updated_by = models.CharField(max_length=NORMAL_SIZE, null=True, blank=True)

    create_date = models.DateTimeField(null=True, blank=True, editable=False)    
    last_update = models.DateTimeField(null=True, blank=True)

    class Meta:
        abstract = True


class TimeLog(BaseModel):
    
    """
        Time log model. This model store time registered by users in tasks and other events. Time log could be started
        stoped and paused.
    """
    
    started = models.DateTimeField(null=True, blank=True)    
    stoped = models.DateTimeField(null=True, blank=True)
    paused = models.IntegerField(null=True, blank=True, default=0)
    status = models.CharField(max_length=NAME_SIZE, default=STOPPED, choices=TIME_STATUS)
    
    #Foreign KEYS
    user = models.ForeignKey(User, null=True, blank=True)


class Project(BaseModel):
    
    """
       Projects that will be managed by user
    """
    
    name = models.CharField(max_length=NAME_SIZE)
    description = models.CharField(max_length=DESCRIPTION_SIZE, blank=True, null=True,)
    
    user = models.ManyToManyField(User) 
    scrum_master = models.ForeignKey(User, blank=True, null=True, related_name="scrum_master_project")
    product_owner = models.ForeignKey(User, blank=True, null=True, related_name="product_owner_project") 
    
    # Reverse url for project specific settings
    def get_url(self):
        return reverse('sprint.views.sprint', kwargs={'id_project': self.pk})
    
    def create_sprint_url(self):
        return reverse('sprint.planning1.views.create_sprint', kwargs={'id_project': self.pk})

    
class HasProject(BaseModel):
    
    """
       Abstract class for other models that has projects
    """
    
    status = models.CharField(max_length=INT_SIZE, default=OPENED, choices=STATUS)
    
    #Foreign KEYS:
    project = models.ForeignKey(Project)
    
    class Meta:
        abstract = True


class Milestone(HasProject):
    
    """
        Milestone is mark of all sprint and history must have. If one history does not 
        have milestone it is in product backlog.
    """
    
    name = models.CharField(max_length=NAME_SIZE)
    initial = models.DateTimeField(null=True, blank=True) 
    end = models.DateTimeField(null=True, blank=True)
        
    
class Sprint(HasProject):  
    
    """
        Sprint is an event that join all histories in one period of time, it must have be completed in the end of deadline
    """
    
    name = models.CharField(max_length=NAME_SIZE)
    goal = models.CharField(max_length=DESCRIPTION_SIZE)
    number = models.IntegerField(null=True, blank=True)
    initial = models.DateTimeField(null=True, blank=True) 
    end = models.DateTimeField(null=True, blank=True)
    dailly = models.DateTimeField(null=True, blank=True)
    dailly_time = models.ForeignKey(TimeLog, null=True, blank=True, related_name="dailly_time")
    review = models.DateTimeField(null=True, blank=True)
    review_time = models.ForeignKey(TimeLog, null=True, blank=True, related_name="review_time")
    planning1 = models.DateTimeField(null=True, blank=True)
    planning1_time = models.ForeignKey(TimeLog, null=True, blank=True, related_name="planning1_time")
    planning2 = models.DateTimeField(null=True, blank=True)
    planning2_time = models.ForeignKey(TimeLog, null=True, blank=True, related_name="planning2_time")
    retrospective = models.DateTimeField(null=True, blank=True)
    retrospective_time = models.ForeignKey(TimeLog, null=True, blank=True, related_name="retrospective_time")
    
    sprint_status = models.CharField(max_length=NAME_SIZE, default=PLANNING_HISTORY, choices=SPRINT_STATUS)
    
    milestone = models.ForeignKey(Milestone, null=True, blank=True)
    
    # Functions for sprint
    def edit_sprint_url(self):
        return "/sprint/planning1/edit/" + str(self.pk)

    # Functions for sprint
    def sprint_url_status(self):
        if self.sprint_status == PLANNING_HISTORY:
            return "/sprint/planning1/edit/" + str(self.pk)
        elif self.sprint_status == PLANNING_TASK:
            return "/sprint/planning2/edit/" + str(self.pk)

class History(HasProject):
    
    """
        
    """
    
    name = models.CharField(max_length=DESCRIPTION_SIZE)
    description = models.CharField(max_length=DESCRIPTION_SIZE, null=True, blank=True)
    estimate = models.IntegerField(max_length=INT_SIZE, null=True, blank=True)
    priority = models.IntegerField(max_length=INT_SIZE, null=True, blank=True)
    state = models.CharField(max_length=INT_SIZE, default=OPENED, choices=HISTORY_STATUS)
    
    tags = TagField()
    
    #Foreign KEYS
    sprint = ForeignKey(Sprint, null=True, blank=True)
    milestone = models.ForeignKey(Milestone, null=True, blank=True)
    
    def estimate_url(self):
        return reverse('sprint.planning1.views.estimate_history', kwargs={'id_history': self.pk})        
    

class HasHistory(HasProject):
    
    """
        All objects that has history
    """
    
    #Foreign KEYS:
    history = models.ForeignKey(History, null=True, blank=True)
    hours = models.ManyToManyField(TimeLog, null=True, blank=True)
    class Meta:
        abstract = True
        
        
class Task(HasHistory):
    
    ttype = models.CharField(max_length=TINY_SIZE, default=TASK, choices=TASKS_TYPE)
    
    name = models.CharField(max_length=NAME_SIZE,)
    description = models.CharField(max_length=DESCRIPTION_SIZE, null=True, blank=True)

    reopened = models.IntegerField(max_length=INT_SIZE, null=True, blank=True)
    priority = models.IntegerField(max_length=INT_SIZE, null=True, blank=True)
    severity = models.CharField(max_length=TINY_SIZE, default=MEDIUM, choices=SEVERITY_TYPE)


#############################################################################################################
# DJANGO USER MODEL
#############################################################################################################

class UserSettings(models.Model):
    
    """
    """
    
    
